/*
 *         (C) COPYRIGHT NBI Limited
 *              ALL RIGHT RESERVED
 *
 * File        : fastflow/core/macros.h
 * Authors     : dzhang
 * Create Time : 2021/09/03 09:45:37
 * Description :
 *
 */

#ifndef __FASTFLOW_CORE_MACROS_H___
#define __FASTFLOW_CORE_MACROS_H___

#include <stdint.h>
#include <iostream>
#include "fastflow/core/string_utils.h"

// define namepsace
#define CC_NAME_SPACE_NAME fastflow
#define USING_NAME_SPACE using namespace CC_NAME_SPACER_NAME;

// Interface visibility
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#ifdef __GNUC__
#define PUBLIC __attribute__((dllexport))
#else  // __GNUC__
#define PUBLIC __declspec(dllexport)
#endif  // __GNUC__
#else   // BUILDING_DLL
#ifdef __GNUC__
#define PUBLIC __attribute__((dllimport))
#else
#define PUBLIC __declspec(dllimport)
#endif  // __GNUC__
#endif  // BUILDING_DLL
#define LOCAL
#else  // _WIN32 || __CYGWIN__
#if __GNUC__ >= 4
#define PUBLIC __attribute__((visibility("default")))
#define LOCAL __attribute__((visibility("hidden")))
#else
#define PUBLIC
#define LOCAL
#endif
#endif

// A macro to disallow the copy constructor and operator= functions
// This is usually placed in the private: declarations for a class.
#define FASTFLOW_DISALLOW_COPY_AND_ASSIGN(TypeName)                                                                    \
    TypeName(const TypeName &) = delete;                                                                               \
    void operator=(const TypeName &) = delete

#ifdef __has_builtin
#define FASTFLOW_HAS_BUILTIN(x) __has_builtin(x)
#else
#define FASTFLOW_HAS_BUILTIN(x) 0
#endif

// We need to disable this for GPU builds, though, since nvcc8 and older
// don't recognize `__builtin_expect` as a builtin, and fail compilation.
#if (!defined(__NVCC__)) && (FASTFLOW_HAS_BUILTIN(__builtin_expect) || (defined(__GNUC__) && __GNUC__ >= 3))
#define FASTFLOW_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define FASTFLOW_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define FASTFLOW_PREDICT_FALSE(x) (x)
#define FASTFLOW_PREDICT_TRUE(x) (x)
#endif

#define FASTFLOW_ATTRIBUTE_NORETURN __attribute__((noreturn))
#define FASTFLOW_ATTRIBUTE_COLD __attribute__((cold))

#ifndef FASTFLOW_MUST_USE_RESULT
#define FASTFLOW_MUST_USE_RESULT __attribute__((warn_unused_result))
#endif

// Macros to disable the copy and/or move ctor and assignment methods
// These are usually placed in the private: declarations for a class.

#define FASTFLOW_DISALLOW_COPY(TypeName) TypeName(const TypeName&) = delete

#define FASTFLOW_DISALLOW_ASSIGNMENT(TypeName) TypeName& operator=(const TypeName&) = delete

#define FASTFLOW_DISALLOW_COPY_AND_ASSIGNMENT(TypeName) \
  FASTFLOW_DISALLOW_COPY(TypeName);                     \
  FASTFLOW_DISALLOW_ASSIGNMENT(TypeName)

#define FASTFLOW_DISALLOW_MOVE(TypeName) \
  TypeName(TypeName&&) = delete;            \
  TypeName& operator=(TypeName&&) = delete

#define FASTFLOW_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(TypeName) \
  FASTFLOW_DISALLOW_COPY_AND_ASSIGNMENT(TypeName);           \
  FASTFLOW_DISALLOW_MOVE(TypeName)

#ifdef _MSC_VER
typedef signed __int8 int8;
typedef __int16 int16;
typedef __int32 int32;
typedef __int64 int64;

typedef unsigned __int8 uint8;
typedef unsigned __int16 uint16;
typedef unsigned __int32 uint32;
typedef unsigned __int64 uint64;
#else
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;

typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
#endif

#define ML_PRINT(format, ...) printf(format, ##__VA_ARGS__)
#define ML_ERROR(format, ...) printf(format, ##__VA_ARGS__)

#define CLIP(x, y) (x < 0 ? 0 : (x > y ? y : x))

#define ALIMIN(x, y) ((x) < (y) ? (x) : (y))
#define ALIMAX(x, y) ((x) > (y) ? (x) : (y))

#define UP_DIV(x, y) (((x) + (y) - (1)) / (y))
#define ROUND_UP(x, y) (((x) + (y) - (1)) / (y) * (y))
#define ALIGN_UP4(x) ROUND_UP((x), 4)
#define ALIGN_UP8(x) ROUND_UP((x), 8)
#if (__arm__ || __aarch64__) && (defined(__ARM_NEON__) || defined(__ARM_NEON))
#define ML_USE_NEON
#endif

// #define MAX_TENSOR_DIM 6
// enum ML_DATA_FORMAT {
//     ML_DATA_FORMAT_NCHW = 0,
//     ML_DATA_FORMAT_NHWC = 1,
//     ML_DATA_FORMAT_NC4HW4 = 2,
//     ML_DATA_FORMAT_NHWC4 = 3,
//     ML_DATA_FORMAT_UNKNOWN = 4,
//     ML_DATA_FORMAT_MIN = ML_DATA_FORMAT_NCHW,
//     ML_DATA_FORMAT_MAX = ML_DATA_FORMAT_UNKNOWN
// };

// enum DataType {
//     DataType_DT_INVALID = 0,
//     DataType_DT_FLOAT = 1,
//     DataType_DT_DOUBLE = 2,
//     DataType_DT_INT32 = 3,
//     DataType_DT_UINT8 = 4,
//     DataType_DT_INT16 = 5,
//     DataType_DT_INT8 = 6,
//     DataType_DT_STRING = 7,
//     DataType_DT_COMPLEX64 = 8,
//     DataType_DT_INT64 = 9,
//     DataType_DT_BOOL = 10,
//     DataType_DT_QINT8 = 11,
//     DataType_DT_QUINT8 = 12,
//     DataType_DT_QINT32 = 13,
//     DataType_DT_BFLOAT16 = 14,
//     DataType_DT_QINT16 = 15,
//     DataType_DT_QUINT16 = 16,
//     DataType_DT_UINT16 = 17,
//     DataType_DT_COMPLEX128 = 18,
//     DataType_DT_HALF = 19,
//     DataType_DT_RESOURCE = 20,
//     DataType_DT_VARIANT = 21,
//     DataType_MIN = DataType_DT_INVALID,
//     DataType_MAX = DataType_DT_VARIANT
// };

#ifdef DEBUG
#define ML_ASSERT(x)                                                                                                   \
    {                                                                                                                  \
        int res = (x);                                                                                                 \
        if (!res) {                                                                                                    \
            printf("Error for %s, %d\n", __FILE__, __LINE__);                                                          \
            assert(res);                                                                                               \
        }                                                                                                              \
    }
#else
#define ML_ASSERT(x)                                                                                                   \
    {                                                                                                                  \
        int res = (x);                                                                                                 \
        if (!res) {                                                                                                    \
            printf("Error for %d\n", __LINE__);                                                                        \
        }                                                                                                              \
    }
#endif

#endif  // __FASTFLOW_CORE_MACROS_H___